package yanyan.com.tochar;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.entity.LocalMedia;



import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import io.microshow.rxffmpeg.RxFFmpegInvoke;
import io.microshow.rxffmpeg.RxFFmpegSubscriber;
import yanyan.com.tochar.adpter.FullyGridLayoutManager;
import yanyan.com.tochar.adpter.GridImageAdapter;
import yanyan.com.tochar.beans.VideoThreadInfo;
import yanyan.com.tochar.thread.VideoThreadTask;
import yanyan.com.tochar.utils.CoreUtil;
import yanyan.com.tochar.utils.EmptyUtils;
import yanyan.com.tochar.utils.PictureSelectUtil;
import yanyan.com.tochar.utils.ProgressDiaolog;
import yanyan.com.tochar.utils.StringUtil;
import yanyan.com.tochar.utils.ToastUtil;

public class VideoTocharActivity extends Activity implements CompoundButton.OnCheckedChangeListener {
    private RecyclerView recyclerView;
    private GridImageAdapter adapter;
    private List imgList= new ArrayList<>();//图片集合
    private ImageView imageView;
    private ProgressDiaolog diaolog=null;
    //线程池
    ThreadPoolExecutor pool=  null;
    private EditText test;

    //是否分解完
    private boolean isResolve;
    //是否已提取音频
    private boolean isGetVoice;


    private CheckBox isStr;
    private CheckBox isColor;
    private EditText str;
    private LinearLayout layout1;
    private LinearLayout layout2;
    private EditText CNEd;
    private LinearLayout CNlayout;
    private CheckBox isCN;
    private LinearLayout resLayout;
    private String outPath;
    private TextView resPathTx;
    private Long videoTime;

    private CheckBox isRetainVoice;

    private boolean isSuccess;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_tochar);
        recyclerView=findViewById(R.id.video_tochar_recycler);
//        imageView=findViewById(R.id.video_tochar_image);
//        test=findViewById(R.id.video_tochar_test);
        resLayout=findViewById(R.id.video_tochar_res_layout);

        isStr=findViewById(R.id.video_tochar_isStr);
        isStr.setOnCheckedChangeListener(this);

        isColor=findViewById(R.id.video_tochar_isColor);
        isColor.setOnCheckedChangeListener(this);

        str=findViewById(R.id.video_tochar_str);

        layout1=findViewById(R.id.video_tochar_layout1);

        CNEd=findViewById(R.id.video_tochar_cn_ed);
        CNlayout=findViewById(R.id.video_tochar_cnlayout);

        isCN=findViewById(R.id.video_tochar_iscn);
        isCN.setOnCheckedChangeListener(this);

        resPathTx=findViewById(R.id.video_tochar_res_path);

        isRetainVoice=findViewById(R.id.video_tochar_retain_voice);

        //初始化图片选择
        FullyGridLayoutManager manager = new FullyGridLayoutManager(this, 4, GridLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(manager);
        adapter = new GridImageAdapter(this, new GridImageAdapter.onAddPicClickListener() {
            @Override
            public void onAddPicClick() {
                PictureSelectUtil.selectVideo(VideoTocharActivity.this,3306);
            }
        });
        adapter.setList(imgList);
        adapter.setSelectMax(1);
        recyclerView.setAdapter(adapter);
        pool=  new ThreadPoolExecutor(8,10,0,
                TimeUnit.SECONDS,new LinkedBlockingQueue<>());

        //统计各功能
        CoreUtil.statisticalFuns(this,"video_tochar");

    }

    /**
     * 选择图片事件
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==RESULT_OK){
            imgList = PictureSelector.obtainMultipleResult(data);
            adapter.setList(imgList);
            adapter.notifyDataSetChanged();
        }
    }


    /**
     * 点击生成事件
     * @param view
     */
    public void getVideo(View view){
        if(imgList.size()>0){
            resLayout.setVisibility(View.GONE);
            boolean color=this.isColor.isChecked();
            boolean isCN=this.isCN.isChecked();
            String textStr="";
            if(isCN){
                textStr=this.CNEd.getText().toString();
            }else {
                textStr=this.str.getText().toString();
            }


            LocalMedia localMedia= (LocalMedia) imgList.get(0);
            String path;
            if(CoreUtil.isAndroidQ()){
                path= localMedia.getAndroidQToPath();
            }else {
                path= localMedia.getPath();
            }
            clearCache();
            videoToChar(color,textStr,path,isCN);
        }else {
            ToastUtil.showLongToast(this,"请选择视频");
        }
    }


    /**
     * 视频转字符视频方法
     * @param isColor
     * @param str
     * @param videoPath
     */
    private void videoToChar(boolean isColor,String str,String videoPath,boolean isCN){
        outPath="";
        isSuccess=false;
        diaolog=new ProgressDiaolog(this,"正在生成视频");
        diaolog.show();
        new Thread(new Runnable() {
            @Override
            public void run() {
                MediaMetadataRetriever media = new MediaMetadataRetriever();
                //配置视频资源
                media.setDataSource(videoPath);
                //获取视频时长
                String timeString =  media.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                Long time = Long.valueOf(timeString);
                videoTime=time;
                int times= (int) (time/1000);
                if(times<1){
                    times=1;
                }
                //获取全部帧数
                String fpsStr = media.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT);
                Long fps=Long.valueOf(fpsStr);
                int intFps=Long.valueOf(fps).intValue();

                int avgFps = calculateFps(time, fps);
                //分解文件
                isResolve=false;
                resolveVideo(videoPath,avgFps);
                //扫描分解情况，未分解不往下执行
                while (!isResolve){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                String cachePath = PictureSelectUtil.getCachePath(VideoTocharActivity.this);
                File cacheFile=new File(cachePath);
                File[] fileList=cacheFile.listFiles();

                //获取音频
                isGetVoice=false;
                String voicePath = getVoiceByVideo(videoPath);
                //扫描获取音频情况，未获取不往下执行
                while (!isGetVoice){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                //初始化map
                VideoThreadInfo.initMap();

                intFps=fileList.length;
                //生成随机文件名
                String outName= UUID.randomUUID().toString().substring(0,6);
                for (int i=0;i<fileList.length;i++){
                    //扫描线程池的数量
                    while (true){
                        int index= VideoThreadInfo.getIndex();
                        if(i-index>4){
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }else {
                            break;
                        }
                    }
                    File imageFile=fileList[i];
                    String name = imageFile.getName();
                   boolean isImg= name.indexOf("fps-")>-1;
                   //判断是否是图片
                   if(isImg){
                       String indexByName = getIndexByName(name);
                       String imgPath=imageFile.getAbsolutePath();
                       Bitmap bitmap = PictureSelectUtil.getBitmap(imgPath);
                       VideoThreadInfo info=new VideoThreadInfo(VideoTocharActivity.this,outName+"_"+indexByName+".png",bitmap,isColor,str,isCN);
                       VideoThreadTask task=new VideoThreadTask(info);
                       pool.execute(task);
                   }

                    //处理进度
                    int pro=VideoThreadInfo.getIndex()*100/(intFps*2);
                    Message message=new Message();
                    message.arg1=pro;
                    handler.sendMessage(message);

                }
                //扫描处理进度
                while (true){
                    Integer integer= VideoThreadInfo.getIndex();
                    //处理进度
                    int pro=integer*100/(intFps*2);
                    Message message=new Message();
                    message.arg1=pro;
                    handler.sendMessage(message);
                    if(integer==intFps){
                        break;
                    }
                }
                ImageToVideo(outName,times+" ",voicePath,avgFps);
            }
        }).start();
    }



    final Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            diaolog.setTitle("正在制作视频");
            super.handleMessage(msg);
            int pro= msg.arg1;
            diaolog.setProgress(pro);
            if(pro==100 && isSuccess){
                resLayout.setVisibility(View.VISIBLE);
                resPathTx.setText("视频路径:"+outPath);
                try {

                } catch (Exception e) {
                    e.printStackTrace();
                }
                diaolog.hide();
                ToastUtil.showLongToast(VideoTocharActivity.this,"生成成功");
            }
        }
    };


    /**
     * 图片转视频
     * @param name
     * @param times
     * @param voicePath
     * @param agvFps
     */
    public void ImageToVideo(String name,String times,String voicePath,int agvFps){
        //ffmpeg -threads 2 -loop 0 -f image2 -r 1 -i /storage/emulated/0/QezlPro/%1d-0ad271.png -vcodec libx264 -t 3 /storage/emulated/0/QezlPro/70157f.mp4
       //是否保留音频
        boolean isVoice=isRetainVoice.isChecked();
        String videoName=  UUID.randomUUID().toString().substring(0,6);
        String outpath=PictureSelectUtil.getPhoneRootPath(VideoTocharActivity.this)+videoName+".mp4";
        String imagePath =PictureSelectUtil.getCachePath(this)+name+"_%05d.png";
        System.out.println("imagePath:"+imagePath);
        String ins="ffmpeg -threads 2 -loop 0 -f image2 -r ";
        ins+=agvFps;
        ins+=" -i ";
        ins+=imagePath;
        //是否保留音频
        if(isVoice){
            ins+=" -i ";
            ins+=voicePath;
        }
        ins+=" -vcodec libx264 -t ";
        ins+=times;
        ins+=outpath;
        System.out.println("outPath:"+outpath);
        System.out.println("执行代码："+ins);
        CoreUtil.copy(ins,this);
        try {
             audioRevel(ins, new OnVideoState() {
                @Override
                public void finsh() {
                    outPath=outpath;
                    if(CoreUtil.isAndroidQ()){

                    }else {
                        VideoTocharActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + outpath)));
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void TestVideo(View view) throws Exception {
        String s = test.getText().toString();
        audioRevel(s, new OnVideoState() {
            @Override
            public void finsh() {
                ToastUtil.showLongToast(VideoTocharActivity.this,"完成");

            }
        });
    }

    /**
     * 获取图片下标
     * @param name
     * @return
     */
    public String getIndexByName(String name){
      String index= StringUtil.getMiddleStr(name,"fps-",".png");
      int in=Integer.parseInt(index);
      in--;
      String ss=String.format("%5d",in).replace(" ","0");
//      index=in+"";
    return ss;
    }

    /**
     * 提取视频中的音频
     * @param videoPath
     * @return
     */
    public String getVoiceByVideo(String videoPath){
        //ffmpeg -i temp.mp4 -f mp3 -vn temp.mp3
        String cachePath=PictureSelectUtil.getCachePath(this)+"voice.mp3";
        String ins="ffmpeg -i ";
        ins+=videoPath;
        ins+=" -f mp3 -vn ";
        ins+=cachePath;
        excuteFfmpeg(ins, new OnVideoState() {
            @Override
            public void finsh() {
                isGetVoice=true;
            }
        });
        return cachePath;
    }

    /**
     * 分解视频
     * @param videoPath
     */
    public void resolveVideo(String videoPath,int avgFps){
        //ffmpeg -i /storage/emulated/0/qqbrowser/视频/downloadfile(1).mp4 -r 5 /storage/emulated/0/QezlPro/cache/ fps%05d.j
        String cachePath=PictureSelectUtil.getCachePath(this);
        String ins="ffmpeg -i /";
        ins+=videoPath;
        ins+=" -r ";
        ins+=avgFps;
        ins+=" ";
        ins+=cachePath;
        ins+="fps-%05d.png";
        excuteFfmpeg(ins, new OnVideoState() {
            @Override
            public void finsh() {
                isResolve=true;
            }
        });

    }



    /**
     * 合并视频代码
     * @param text
     * @param onVideoState
     * @throws Exception
     */
    public void audioRevel(String text,OnVideoState onVideoState){
        RxFFmpegInvoke.getInstance().setDebug(true);
        String[] commands = text.split(" ");
        RxFFmpegInvoke.getInstance().runCommandRxJava(commands).subscribe(new RxFFmpegSubscriber() {
            @Override
            public void onFinish() {
                Message message=new Message();
                isSuccess=true;
                message.arg1=100;
                handler.sendMessage(message);
                onVideoState.finsh();
                ToastUtil.showLongToast(VideoTocharActivity.this, "完成");
            }

            @Override
            public void onProgress(int progress, long progressTime) {
                //progressTime/1000/videoTime*100/2
                int prog= (int) (progressTime/5/videoTime);

                Message message=new Message();
                message.arg1=50+prog;
                handler.sendMessage(message);
            }

            @Override
            public void onCancel() {

            }

            @Override
            public void onError(String message) {
                ToastUtil.showLongToast(VideoTocharActivity.this, "错误：" + message);
            }
        });
    }

    /**
     * 执行ffmpeg代码，为了不影响进度框
     * @param text
     * @param onVideoState
     */
    public void excuteFfmpeg(String text,OnVideoState onVideoState){
        RxFFmpegInvoke.getInstance().setDebug(true);
        String[] commands = text.split(" ");
        RxFFmpegInvoke.getInstance().runCommandRxJava(commands).subscribe(new RxFFmpegSubscriber() {
            @Override
            public void onFinish() {
                onVideoState.finsh();
            }

            @Override
            public void onProgress(int progress, long progressTime) {
            }

            @Override
            public void onCancel() {

            }

            @Override
            public void onError(String message) {
                ToastUtil.showLongToast(VideoTocharActivity.this, "错误：" + message);
            }
        });

    }

    public void openResVideo(View view){
        if(EmptyUtils.isNotEmpty(outPath)){
            openVideo(outPath);
        }else {
            ToastUtil.showLongToast(this,"没有找到视频，请重新生成");
        }
    }

    /**
     * 打开自带浏览器播放视频
     * @param path
     */
    private void openVideo(String path){
        Intent intent=new Intent(Intent.ACTION_VIEW);
        File file=new File(path);
        Uri uri=Uri.fromFile(file);
        intent.setDataAndType(uri,"video/*");
        startActivity(intent);
    }
    /**
     * 计算平均帧数
     * @param time
     * @param fps
     * @return
     */
    public int calculateFps(Long time,Long fps){
       Long resFps= fps*1000/time;
        System.out.println("ResFps:"+resFps);
        return resFps<1?1: resFps.intValue();

    }    /**
     * 清除缓存内容
     */
    public void clearCache(){
        String cachePath = PictureSelectUtil.getCachePath(this);
        File file=new File(cachePath);
        for (File f:file.listFiles()){
            f.delete();
        }


    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        int id=buttonView.getId();
        switch (id){
            case R.id.video_tochar_isStr:
                if(isChecked){
                    layout1.setVisibility(View.VISIBLE);
                    CNlayout.setVisibility(View.GONE);
                    isCN.setChecked(false);
                }else {
                    CNlayout.setVisibility(View.VISIBLE);
                    isCN.setChecked(true);
                    layout1.setVisibility(View.GONE);
                }
                break;
            case R.id.video_tochar_iscn:
                if(isChecked){
                    isStr.setChecked(false);
                    layout1.setVisibility(View.GONE);
                    CNlayout.setVisibility(View.VISIBLE);
                }else {
                    isStr.setChecked(true);
                    layout1.setVisibility(View.VISIBLE);
                    CNlayout.setVisibility(View.GONE);
                }
                break;
        }

    }

    public interface OnVideoState {
        public void finsh();
    }

    public void getVideoInfo(View view){
        if(imgList.size()>0){
            LocalMedia localMedia= (LocalMedia) imgList.get(0);
            String path= localMedia.getPath();
            MediaMetadataRetriever media = new MediaMetadataRetriever();
            //配置视频资源
            media.setDataSource(path);
            //获取视频时长
            String timeString =  media.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
            Long time = Long.valueOf(timeString);
            int times= (int) (time/1000);
            if(times<1){
                times=1;
            }
            //获取全部帧数
            String fpsStr = media.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT);
            Long fps=Long.valueOf(fpsStr);
            int intFps=Long.valueOf(fps).intValue();

            int avgFps = calculateFps(time, fps);
            test.setText("time:"+time+"\nfps："+fps+"\navgFps:"+avgFps);

        }

    }
}
